package org.kernely.ui.profile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.kernely.security.dao.UserDetailsDAO;
import org.kernely.security.persistence.User;
import org.kernely.security.persistence.UserDetails;
import org.kernely.ui.MainApplication;
import org.kernely.ui.mvp.KernelyEvent;
import org.kernely.ui.mvp.KernelyEventReceiver;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.terminal.FileResource;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.SucceededEvent;

/**
 * Presenter of user profile page.
 */
@SuppressWarnings("serial")
public class KernelyProfilePresenter extends KernelyPresenter<KernelyProfileView> implements KernelyEventReceiver, Upload.SucceededListener, Upload.FailedListener, Upload.Receiver {

	private File file;

	/**
	 * @see org.kernely.core.service.IKernelyPresenter#bind()
	 */
	@SuppressWarnings("serial")
	@Override
	public final void bind() {
		// Registering as an event receiver to be called by KernelyProfileAttachedEvent
		MainApplication.getEventBus().addListener(this);

		// Management of pictures
		this.view.getUploadPicture().setReceiver(this);
		this.view.getUploadPicture().addListener((Upload.SucceededListener) this);
		this.view.getUploadPicture().addListener((Upload.FailedListener) this);
		// Associate a listener to save buttons
		this.view.getSavePersoButton().addListener(new ClickListener(){
			private static final long serialVersionUID = -6511936712444287550L;
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick (Button.ClickEvent event) {
				savePerso();
			}
		});
		
		this.view.getSaveContactButton().addListener(new ClickListener(){
			private static final long serialVersionUID = -6511936712444287550L;
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick (Button.ClickEvent event) {
				saveContact();
			}
		});
		
		this.view.getSaveSocialButton().addListener(new ClickListener(){
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick (Button.ClickEvent event) {
				saveSocial();
			}
		});
		// Associate a listener to this button
		this.view.getResetPictureButton().addListener(new ClickListener(){
			private static final long serialVersionUID = -5498481942943924L;
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick (Button.ClickEvent event) {
				resetPicture();
			}
		});

		// Auto-fill of fields
		User u = MainApplication.getSecurityService().getCurrentUser();
		UserDetailsDAO uddao = new UserDetailsDAO();
		UserDetails ud = uddao.getUserDetails(u);

		this.view.getCivility().setValue(ud.getCivility());
		this.view.getFirstnameField().setValue(ud.getFirstname());
		this.view.getNameField().setValue(ud.getName());
		this.view.getActivityField().setValue(ud.getActivity());
		this.view.getEmailField().setValue(ud.getMail());
		this.view.getDescriptionField().setValue(ud.getDescription());
		this.view.getPhoneField().setValue(ud.getPhone());
		this.view.getAddressField().setValue(ud.getAddress());
		this.view.getSkypeField().setValue(ud.getSkype());
		this.view.getViadeoField().setValue(ud.getViadeo());
		this.view.getLinkedInField().setValue(ud.getLinkedin());
		this.view.getTwitterField().setValue(ud.getTwitter());
		this.view.getEmailField().setValue(ud.getMail());

	}

	/**
	 * This method is called to remove the picture of the user, and replace by the default picture.
	 */
	private void resetPicture(){
		// We remove the picture from user
		User u = MainApplication.getSecurityService().getCurrentUser();
		UserDetailsDAO uddao = UserDetailsDAO.getInstance();
		UserDetails ud = uddao.getUserDetails(u);
		ud.setImage("");
		uddao.updateUserDetails(ud);

		//We display the (default) picture
		displayPicture();
	}

	/**
	 * Method called to save user's changes.
	 */
	public final void savePerso(){

		try {
			// We check the validity of user's inputs
			view.getNameField().validate();
			view.getFirstnameField().validate();
			view.getActivityField().validate();
			view.getDescriptionField().validate();
			
			User u = MainApplication.getSecurityService().getCurrentUser();
			UserDetailsDAO uddao = UserDetailsDAO.getInstance();
			UserDetails ud = uddao.getUserDetails(u);

			// When fields are validated, we update data in base
			ud.setCivility((Integer)view.getCivility().getValue());			
			ud.setName(view.getNameField().toString());
			ud.setFirstname(view.getFirstnameField().toString());
			ud.setActivity(view.getActivityField().toString());
			ud.setDescription(view.getDescriptionField().toString());
			
			uddao.updateUserDetails(ud);
			MainApplication.getEventBus().broadcastEvent(new KernelyProfileEvent(this));

			// We update the image
			displayPicture();
			
			view.getWindow().showNotification(new KernelyNotification("Profile successfully updated.", KernelyNotification.INFO_ICON));
		}
		catch (InvalidValueException e){
			//Log the failure on screen, to give feedback to the user
			view.getWindow().showNotification(new KernelyNotification(e.getMessage(), KernelyNotification.WARNING_ICON));
		}

	}
	
	/**
	 * Save informations about the contacts of the user.
	 */
	public final void saveContact(){
		try {
			// We check the validity of user's inputs
			view.getEmailField().validate();
			view.getSkypeField().validate();
			view.getPhoneField().validate();
			view.getAddressField().validate();
			
			User u = MainApplication.getSecurityService().getCurrentUser();
			UserDetailsDAO uddao = UserDetailsDAO.getInstance();
			UserDetails ud = uddao.getUserDetails(u);

			
			ud.setMail(view.getEmailField().toString());
			ud.setPhone(view.getPhoneField().toString());
			ud.setAddress(view.getAddressField().toString());
			ud.setSkype(view.getSkypeField().toString());
			
			uddao.updateUserDetails(ud);
			MainApplication.getEventBus().broadcastEvent(new KernelyProfileEvent(this));
			
			view.getWindow().showNotification(new KernelyNotification("Profile successfully updated.", KernelyNotification.INFO_ICON));
		}
		catch (InvalidValueException e){
			//Log the failure on screen, to give feedback to the user
			view.getWindow().showNotification(new KernelyNotification(e.getMessage(), KernelyNotification.WARNING_ICON));
		}
	}
	
	/**
	 * Save informations about social networks
	 */
	public final void saveSocial(){
		try {
			// We check the validity of user's inputs
			view.getViadeoField().validate();
			view.getLinkedInField().validate();
			view.getTwitterField().validate();
			
			User u = MainApplication.getSecurityService().getCurrentUser();
			UserDetailsDAO uddao = UserDetailsDAO.getInstance();
			UserDetails ud = uddao.getUserDetails(u);

			// When fields are validated, we update data in base
			ud.setViadeo(view.getViadeoField().toString());
			ud.setLinkedin(view.getLinkedInField().toString());
			ud.setTwitter(view.getTwitterField().toString());
			
			uddao.updateUserDetails(ud);
			MainApplication.getEventBus().broadcastEvent(new KernelyProfileEvent(this));
			
			view.getWindow().showNotification(new KernelyNotification("Profile successfully updated.", KernelyNotification.INFO_ICON));
		}
		catch (InvalidValueException e){
			//Log the failure on screen, to give feedback to the user
			view.getWindow().showNotification(new KernelyNotification(e.getMessage(), KernelyNotification.WARNING_ICON));
		}
	}

	/**
	 * Called when the upload has succeded
	 */
	@Override
	public final void uploadSucceeded(SucceededEvent event) {
		// Log the upload on screen.
		this.view.getWindow().showNotification(new KernelyNotification("Your image has been successfully uploaded.", KernelyNotification.INFO_ICON));

		// When upload succeeded, we save the picture in database.
		
		User u = MainApplication.getSecurityService().getCurrentUser();
		UserDetailsDAO uddao = UserDetailsDAO.getInstance();
		UserDetails ud = uddao.getUserDetails(u);
		ud.setImage(this.file.getName());
		uddao.updateUserDetails(ud);

		// Display the uploaded file in the image panel.
		displayPicture();
	}


	/**
	 * Called when the upload has failed
	 */
	@Override
	public final void uploadFailed(FailedEvent event) {
		// Log the failure on screen.
		this.view.getWindow().showNotification(new KernelyNotification("An error has occured, your image has not been uploaded...", KernelyNotification.ERROR_ICON));
	}


	/**
	 * Called when an upload is needed.
	 */
	@Override
	public final OutputStream receiveUpload(String filename, String mimeType) {
		FileOutputStream fos = null; // Output stream to write to
		//Retrieve the file extension
		String ext = filename.substring(filename.lastIndexOf('.'));
		//Rename the file with the user's mail. (Unicity)
		User u = MainApplication.getSecurityService().getCurrentUser();
		UserDetailsDAO uddao = new UserDetailsDAO();
		UserDetails ud = uddao.getUserDetails(u);
		// Rename the picture with the mail of the current user to make unicity
		String fname = ud.getMail() + ext;

		file = new File("/tmp/uploads/" + fname);
		try {
			// Open the file for writing.
			fos = new FileOutputStream(file);
		} catch (final java.io.FileNotFoundException e) {
			// Error while opening the file. Not reported here.
			e.printStackTrace();
			return null;
		}

		return fos; // Return the output stream to write to
	}

	/**
	 * @see org.kernely.ui.mvp.KernelyEventReceiver#handleKernelyEvent(KernelyEvent)
	 */
	@Override
	public final void handleKernelyEvent(KernelyEvent event) {
		if (event instanceof KernelyProfileAttachedEvent){
			displayPicture();
		}
	}

	/**
	 * Display the profile's picture 
	 */
	private void displayPicture(){

		// We get the current user
		User u = MainApplication.getSecurityService().getCurrentUser();
		UserDetailsDAO uddao = new UserDetailsDAO();
		UserDetails ud = uddao.getUserDetails(u);

		// We display his picture, or a default one
		if (ud.getImage() == null || ud.getImage().equals("")){

			//The default image is located in src/main/resources/VAADIN/themes/kernelytheme/img
			if(ud.getCivility() == 0){
				ThemeResource imageResource = new ThemeResource("img/default_male.png");
				this.view.getPictureEmbedded().setSource(imageResource);
			}
			else{
				ThemeResource imageResource = new ThemeResource("img/default_female.png");
				this.view.getPictureEmbedded().setSource(imageResource);
			}
		} else {
			this.file = new File("/tmp/uploads/"+ud.getImage());
			final FileResource imageResource = new FileResource(this.file, this.view.getUploadPicture().getApplication());
			this.view.getPictureEmbedded().setSource(imageResource);
		}

		this.view.getPictureEmbedded().requestRepaint();			

	}

	/**
	 * Called when the presenter is no more visible.
	 */
	@Override
	public final void unset() {
		MainApplication.getEventBus().removeListener(this);
	}
}
